/**
 * Name        : main.c
 * Version     :
 * Description : main definition for FreeRTOS application
 */

/*
 * FreeRTOS includes
 */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
#include "LED/LED.h"
#include "ADC/ADC.h"
#include "Key/Key.h"
#include "Timer/Timer.h"
#include "UART/UART.h"
#include "Preconcentrator/prec.h"
#include "Protocol/Protocol.h"
#include "I2C/i2c.h"
#include "EEPROM/eeprom.h"
#include "Tasks/ApplicationTasks.h"
#include "DAC/dac.h"
#include "GPDMA/GPDMA.h"

#include <stdio.h>

#define USERTASK_STACK_SIZE configMINIMAL_STACK_SIZE
#define mainPASS_STATUS_MESSAGE "All tasks are executing without error."

xSemaphoreHandle xUartReceivedSem;
xTimerHandle xModesTimer;

xSemaphoreHandle xEtco2Received;
xSemaphoreHandle xBreathParamsReceived;

long lExpireCounter = 0;

/* QUEUES */
xQueueHandle xSpeakerParamQueue;
xSemaphoreHandle xAdc2UartSem;

uint16_t count;
float dac_val;

void setupHardware(void) {
	// TODO: Put hardware configuration and initialization in here

	LED_Config();
	UART1_Config(115200);
	//Key_Config();
	ADC_Config();
	Timer1_Config();		//adc trigger
	Timer2_Config();		//speaker
	RIT_Config();			//feedback task trigger
	DAC_Config();
	//SetupETCO2Module();
	ConfigPrecControl();
	GPDMA_Config();
	

	// Warning: If you do not initialize the hardware clock, the timings will be inaccurate
}

/**
 * Simple task that just toggles between to states
 */
void vUserTask1(void *pvParameters) {
	//static int iState = 0;

	portTickType xLastWakeTime;
	const portTickType xFreqency = 1000/portTICK_RATE_MS;
	xLastWakeTime = xTaskGetTickCount();
	printf("Task1\n\r");
	while (1) {
		//vSetSpeakerParams(50,500);
		//printf("Task1 inside\n\r");
		vTaskDelayUntil(&xLastWakeTime, xFreqency);
		//printf("Task1\n\r");
		LED_Toggle(1<<2);
	}
}

void vUserTask2(void *pvParameters) {

/*
#ifdef configGENERATE_RUN_TIME_STATS == 1
	portCHAR WriteBuffer[250];
	signed char *pWriteBuffer;
#endif
*/

	portTickType xLastWakeTime;
	const portTickType xFreqency = 300/portTICK_RATE_MS;
	xLastWakeTime = xTaskGetTickCount();
	//printf("Task2\n\r");
	dac_val = 0;
	while (1) {

		LED_Toggle(1<<3);

		//printf("%X", (PVal.ptime1&0xFF00)>>8);
		//printf("Hello\n\r");
/*
		dac_val += 0.1;
		if(dac_val > 3.3)
			dac_val = 0;
*/
		//ValueDAC(PVal.dac_voltage);

//		printf("Wartosc DAC: %1.1f\n\r", dac_val);
/*
#ifdef configGENERATE_RUN_TIME_STATS == 1
		pWriteBuffer = (signed char*)WriteBuffer;
		//vTaskGetRunTimeStats( (signed char*) pWriteBuffer );

		while(*pWriteBuffer)
		{
			UART_Sendchar(*pWriteBuffer++);
		}
#endif
*/
		//printf("Task2 inside\n\r");
		//vSetSpeakerParams(40,5000);
		//SetPrec300();
		vTaskDelayUntil(&xLastWakeTime, xFreqency);
		//vTaskDelay(1000);
	}
}

void vApplicationTickHook( void ){
	LED_Toggle(1<<0);
}
/**
 * Program entry point 
 */

int main(void) {

	setupHardware();

	//xTaskCreate( vUserTask1, ( signed portCHAR * ) "Task1", USERTASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
	xTaskCreate( vUserTask2, ( signed portCHAR * ) "Task2", USERTASK_STACK_SIZE+100, NULL, tskIDLE_PRIORITY, NULL );

	xTaskCreate( vFeedbackTask, ( signed portCHAR * ) "FeedbackTask", USERTASK_STACK_SIZE+300, NULL, tskIDLE_PRIORITY, NULL );
	xTaskCreate( vReceiveValuesTask, ( signed portCHAR * ) "ReceiveValuesTask", USERTASK_STACK_SIZE+200, NULL, tskIDLE_PRIORITY, NULL );
	xTaskCreate( vSpeakerTask, ( signed portCHAR * ) "SpeakerTask", USERTASK_STACK_SIZE+100, NULL, tskIDLE_PRIORITY, NULL );

	//xTaskCreate( vETCO2Task, ( signed portCHAR * ) "ETCO2Task", USERTASK_STACK_SIZE+100, NULL, tskIDLE_PRIORITY, NULL );
	xModesTimer = xTimerCreate(( signed portCHAR * ) "ModesTimer", 100, pdTRUE, (void * ) 0, vTimerCallback );


	if( xModesTimer == NULL )
	{
	 //The timer was not created.
	}
	else
	{
	 	//Start the timer.  No block time is specified, and even if one was
		//it would be ignored because the RTOS scheduler has not yet been
		//started.
		if( xTimerStart( xModesTimer, 0 ) != pdPASS )
	    {
	    // The timer could not be set into the Active state.
	    }
	}

	TurnOnVoltage();
	//printf("Zaczynamy\n\r");

	/*
	 * Start the scheduler.
	 */
	vTaskStartScheduler();

	/*
	 * Will only get here if there was insufficient memory to create the idle task.
	 */
	return 1;
}

//char *pcGetTaskStatusMessage( void )
//{
	/* Not bothered about a critical section here. */
//	return pcStatusMessage;
//}

void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName )
{
	/* This function will get called if a task overflows its stack. */

	printf("Stack overflow\r\n");
	printf("Task: %s", pcTaskName);
	while(1);

	for( ;; );
}
/*-----------------------------------------------------------*/

void vConfigureTimerForRunTimeStats( void )
{
const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01;

	/* This function configures a timer that is used as the time base when
	collecting run time statistical information - basically the percentage
	of CPU time that each task is utilising.  It is called automatically when
	the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set
	to 1). */

	/* Power up and feed the timer. */
	LPC_SC->PCONP |= 0x02UL;
	LPC_SC->PCLKSEL0 = (LPC_SC->PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);

	/* Reset Timer 0 */
	LPC_TIM0->TCR = TCR_COUNT_RESET;

	/* Just count up. */
	LPC_TIM0->CTCR = CTCR_CTM_TIMER;

	/* Prescale to a frequency that is good enough to get a decent resolution,
	but not too fast so as to overflow all the time. */
	LPC_TIM0->PR =  ( configCPU_CLOCK_HZ / 10000UL ) - 1UL;

	/* Start the counter. */
	LPC_TIM0->TCR = TCR_COUNT_ENABLE;
}
/*-----------------------------------------------------------*/


void vApplicationMallocFailedHook(void){
	printf("Application malloc failed\r\n");
	while(1);
}
